package com.ruoyi.iot.utils;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;

@Slf4j
public class IEEE754Utils {
    /**
     * 字节数组转IEEE 754
     *
     * @param bytes 长度4或者8
     * @author: 若非
     * @date: 2021/9/10 16:57
     */
    public static BigDecimal bytesToSingle(byte[] bytes) {
        if (bytes.length > 8) {
            throw new ArrayIndexOutOfBoundsException("转化失败，字节超出整型大小！");
        }
        String hex = new BigInteger(bytes).toString(16);
        return hexToSingles(hex, bytes.length * 8);
    }

    /**
     * 字节数组转IEEE 754
     *
     * @param hex
     * @param bitLen 32或者64
     * @author: 若非
     * @date: 2021/9/10 16:57
     */
    public static BigDecimal hexToSingles(String hex, int bitLen) {
        if (StrUtil.isBlank(hex)) {
            return BigDecimal.valueOf(0);
        }
        if (bitLen == 32) {
            int i = Integer.parseInt(hex, 16);
            float v = Float.intBitsToFloat(i);
            return new BigDecimal(v);
        }
        if (bitLen == 64) {
            long l = Long.parseLong(hex, 16);
            double d = Double.longBitsToDouble(l);
            return new BigDecimal(d);
        }
        return BigDecimal.valueOf(0);
    }

    /**
     * IEEE 754字符串转十六进制字符串
     *
     * @param f
     * @author: 若非
     * @date: 2021/9/10 16:57
     */
    public static String singleToHexs(float f) {
        int i = Float.floatToIntBits(f);
        String hex = Integer.toHexString(i);
        return hex;
    }

    /**
     * IEEE 754字符串转十六进制字符串
     *
     * @param d
     * @author: 若非
     * @date: 2021/9/10 16:57
     */
    public static String singleToHex(double d) {
        long l = Double.doubleToRawLongBits(d);
        String hex = Long.toHexString(l);
        return hex;
    }

    /**
     * 十六进制字符串转IEEE 754
     *
     * @author: 若非
     * @date: 2021/9/10 16:57
     */
    public static BigDecimal hexToSingle(String hex, int bitLen) {
        if (StrUtil.isBlank(hex) || bitLen != 32 && bitLen != 64) {
            return BigDecimal.valueOf(0);
        }
        String binaryString = fillString(new BigInteger(hex, 16).toString(2), "0", bitLen, true);
        int exponentBitLength = hex.length() == 8 ? 8 : 11;
        int mantissaBitLength = (hex.length() * 4) - exponentBitLength - 1;
        char s = binaryString.charAt(0);//符号位
        String e = binaryString.substring(1, exponentBitLength + 1);
        String m = binaryString.substring(exponentBitLength + 1);
        Double bias = Math.pow(2, exponentBitLength - 1) - 1;
        int exponent = Integer.valueOf(e, 2) - bias.intValue();
        long mantissa = Long.valueOf(m, 2);
        Double res = (1 + (mantissa * Math.pow(2, -mantissaBitLength))) * Math.pow(2, exponent);
        BigDecimal bigDecimal = new BigDecimal(res);
        if (s == '1') {
            return new BigDecimal(0).subtract(bigDecimal);
        }
        return bigDecimal;
    }

    private static String fillString(String src, String c, int len, boolean left) {
        if (StrUtil.isBlank(src) || len <= src.length()) {
            return src;
        }
        int l = src.length();
        for (int i = 0; i < len - l; i++) {
            if (left) {
                src = c + src;
            } else {
                src += c;
            }
        }
        return src;
    }

    /**
     * 把寄存器读数转成 BigDecimal
     *
     * @param: short[]  寄存器读数
     * @Return: 保留两位小数的BigDecimal
     * @Author: Howe
     * @Date: 2025/3/5 下午1:53
     **/
    public static BigDecimal convertRegistersToFloat(short[] shortData) {
        if (shortData.length != 2) {
            return BigDecimal.ZERO;
        }
        int register1 = shortData[0];
        int register2 = shortData[1];
        // 将两个 16 位寄存器合并为一个 32 位整数
        int intBits = (register1 << 16) | (register2 & 0xFFFF);
        // 将 32 位整数转换为浮点数
        BigDecimal bigDecimal = BigDecimal.valueOf(Float.intBitsToFloat(intBits));
        log.info("寄存器读数转换成浮点数：{}", bigDecimal);
        bigDecimal = bigDecimal.setScale(2, RoundingMode.HALF_UP);
        log.info("寄存器读数转换成浮点数保留两位小数：{}", bigDecimal);
        return bigDecimal;
    }

    public static void main(String[] args) {
        short[] shortData = {17244, 0};
        BigDecimal bigDecimal = convertRegistersToFloat(shortData);
        System.out.println(bigDecimal);
    }
}
